package com.hll.api.util;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.hll.api.config.web.DefaultX509TrustManager;
import com.hll.api.config.web.Message;
import com.hll.api.config.web.RespMessage;
import com.hll.api.exception.MyException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.springframework.util.Assert;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * http请求工具类
 *
 * @author 何龙
 */
@Slf4j
public class HttpUtils {
	private static final int READ_TIMEOUT = 60000;

	private static final int CONNECT_TIMEOUT = 60000;

	public static String get(String urlAddr, Map<String, Object> paramsMap) throws Exception {
		return get(urlAddr, paramsMap, READ_TIMEOUT, CONNECT_TIMEOUT);
	}

	public static String get(String urlAddr) throws Exception {
		return get(urlAddr, null, READ_TIMEOUT, CONNECT_TIMEOUT);
	}

	public static String post(String urlAddr, Map<String, Object> paramsMap) throws Exception {
		return post(urlAddr, paramsMap, READ_TIMEOUT, CONNECT_TIMEOUT);
	}

	public static String post(String urlAddr) throws Exception {
		return post(urlAddr, (Map<String, Object>) null, READ_TIMEOUT, CONNECT_TIMEOUT);
	}

	public static String getSSL(String urlAddr, Map<String, Object> paramsMap) throws Exception {
		return getSSL(urlAddr, paramsMap, READ_TIMEOUT, CONNECT_TIMEOUT);
	}

	public static String getSSL(String urlAddr) throws Exception {
		return getSSL(urlAddr, null, READ_TIMEOUT, CONNECT_TIMEOUT);
	}

	public static String postSSL(String urlAddr, Map<String, Object> paramsMap) throws Exception {
		return postSSL(urlAddr, paramsMap, READ_TIMEOUT, CONNECT_TIMEOUT);
	}

	public static String postSSL(String urlAddr) throws Exception {
		return postSSL(urlAddr, (Map<String, Object>) null, READ_TIMEOUT, CONNECT_TIMEOUT);
	}

	public static String postSSL(String urlAddr, String params) throws Exception {
		return postSSL(urlAddr, params, READ_TIMEOUT, CONNECT_TIMEOUT);
	}

	public static byte[] getImg(String img) throws Exception {
		HttpURLConnection conn;
		BufferedReader bufferedReader = null;
		InputStreamReader inputStreamReader = null;
		StringBuilder result = new StringBuilder();
		URL url = new URL(img);
		conn = (HttpURLConnection) url.openConnection();
		conn.connect();
		InputStream in = conn.getInputStream();
		//<1>创建字节数组输出流，用来输出读取到的内容
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		//<2>创建缓存大小
		byte[] buffer = new byte[1024]; // 1KB
		//每次读取到内容的长度
		int len;
		//<3>开始读取输入流中的内容
		while ((len = in.read(buffer)) != -1) { //当等于-1说明没有数据可以读取了
			baos.write(buffer, 0, len);   //把读取到的内容写到输出流中
		}
		in.close();
		baos.close();
		return baos.toByteArray();
	}

	public static byte[] getSSLImg(String urlAddr) throws Exception {
		String line;
		String params = "";
		HttpsURLConnection conn;
		BufferedReader bufferedReader = null;
		InputStreamReader inputStreamReader = null;
		StringBuilder result = new StringBuilder();
		TrustManager[] trustManager = {new DefaultX509TrustManager()};
		// 创建SSLContext
		SSLContext sslContext = SSLContext.getInstance("SSL");
		// 初始化
		sslContext.init(null, trustManager, new java.security.SecureRandom());
		// 获取SSLSocketFactory对象
		SSLSocketFactory ssf = sslContext.getSocketFactory();
		URL url = new URL(urlAddr + params);
		conn = (HttpsURLConnection) url.openConnection();
		// 设置读取超时时间
		conn.setReadTimeout(READ_TIMEOUT);
		// 设置连接超时时间
		conn.setConnectTimeout(CONNECT_TIMEOUT);
		// 设置当前实例使用的SSLSocketFactory
		conn.setSSLSocketFactory(ssf);
		conn.connect();
		InputStream in = conn.getInputStream();
		//<1>创建字节数组输出流，用来输出读取到的内容
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		//<2>创建缓存大小
		byte[] buffer = new byte[1024]; // 1KB
		//每次读取到内容的长度
		int len;
		//<3>开始读取输入流中的内容
		while ((len = in.read(buffer)) != -1) { //当等于-1说明没有数据可以读取了
			baos.write(buffer, 0, len);   //把读取到的内容写到输出流中
		}
		//<5>关闭输入流和输出流
		in.close();
		baos.close();
		return baos.toByteArray();
	}

	/**
	 * 读取 InputStream 到 String字符串中
	 */
	public static String readStream(InputStream in) {
		try {
			//<1>创建字节数组输出流，用来输出读取到的内容
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			//<2>创建缓存大小
			byte[] buffer = new byte[1024]; // 1KB
			//每次读取到内容的长度
			int len;
			//<3>开始读取输入流中的内容
			while ((len = in.read(buffer)) != -1) { //当等于-1说明没有数据可以读取了
				baos.write(buffer, 0, len);   //把读取到的内容写到输出流中
			}
			//<4> 把字节数组转换为字符串
			String content = baos.toString();
			//<5>关闭输入流和输出流
			in.close();
			baos.close();
			//<6>返回字符串结果
			return content;
		} catch (Exception e) {
			e.printStackTrace();
			return e.getMessage();
		}
	}

	/**
	 * http get request
	 */
	public static String get(String urlAddr, Map<String, Object> paramsMap, int connectTimeout, int readTimeout) throws Exception {
		log.debug("get request url: {}, params: {}", urlAddr, JSONObject.toJSONString(paramsMap));
		String line;
		String params = "";
		HttpURLConnection conn = null;
		BufferedReader bufferedReader = null;
		InputStreamReader inputStreamReader = null;
		StringBuilder result = new StringBuilder();
		try {
			if (connectTimeout < 1) {
				connectTimeout = CONNECT_TIMEOUT;
			}
			if (readTimeout < 1) {
				readTimeout = READ_TIMEOUT;
			}
			if (paramsMap != null && !paramsMap.isEmpty()) {
				StringBuilder str = new StringBuilder();
				Set<String> set = paramsMap.keySet();
				for (Object o : set) {
					String key = o.toString();
					if (paramsMap.get(key) == null) {
						continue;
					}
					str.append(key).append("=").append(paramsMap.get(key)).append("&");
				}
				if (str.length() > 0) {
					params = "?" + str.substring(0, str.length() - 1);
				}
			}
			URL url = new URL(urlAddr + params);
			conn = (HttpURLConnection) url.openConnection();
			// 设置读取超时时间
			conn.setReadTimeout(readTimeout);
			// 设置连接超时时间
			conn.setConnectTimeout(connectTimeout);
			conn.connect();
			inputStreamReader = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8);
			bufferedReader = new BufferedReader(inputStreamReader);
			while ((line = bufferedReader.readLine()) != null) {
				result.append(line);
			}
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (inputStreamReader != null) {
				try {
					inputStreamReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (conn != null) {
				try {
					conn.disconnect();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		log.debug("get request url: {},返回值:{}", urlAddr, result.toString());
		return result.toString();
	}

	/**
	 * http post request
	 */
	public static String post(String urlAddr, Map<String, Object> paramsMap, int connectTimeout, int readTimeout) throws Exception {
		log.info("post request url: {}, params: {}", urlAddr, JSONObject.toJSONString(paramsMap));
		String line;
		String params = "";
		HttpURLConnection conn = null;
		BufferedReader bufferedReader = null;
		InputStreamReader inputStreamReader = null;
		OutputStreamWriter outputStreamWriter = null;
		StringBuilder result = new StringBuilder();
		try {
			if (connectTimeout < 1) {
				connectTimeout = CONNECT_TIMEOUT;
			}
			if (readTimeout < 1) {
				readTimeout = READ_TIMEOUT;
			}
			if (paramsMap != null && !paramsMap.isEmpty()) {
				StringBuilder str = new StringBuilder();
				Set<String> set = paramsMap.keySet();
				for (Object o : set) {
					String key = o.toString();
					if (paramsMap.get(key) == null) {
						continue;
					}
					str.append(key).append("=").append(paramsMap.get(key)).append("&");
				}
				if (str.length() > 0) {
					params = str.substring(0, str.length() - 1);
				}
			}
			URL url = new URL(urlAddr);
			conn = (HttpURLConnection) url.openConnection();
			// 设置读取超时时间
			conn.setReadTimeout(readTimeout);
			// 设置连接超时时间
			conn.setConnectTimeout(connectTimeout);
			// 设置是否向HttpURLConnection输出，因为这个是post请求，参数要放在http正文内，
			// 因此需要设为true, 默认情况下是false
			conn.setDoOutput(true);
			// 不使用缓存,默认情况下是true
			conn.setUseCaches(false);
			// 设定请求的方法为"POST",默认是GET
			conn.setRequestMethod("POST");
			if (!params.isEmpty()) {
				// 此处getOutputStream会隐含的进行connect()
				outputStreamWriter = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8);
				// 写入
				outputStreamWriter.write(params);
				// 刷新该流的缓冲
				outputStreamWriter.flush();
			}
			inputStreamReader = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8);
			bufferedReader = new BufferedReader(inputStreamReader);
			while ((line = bufferedReader.readLine()) != null) {
				result.append(line);
			}
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (inputStreamReader != null) {
				try {
					inputStreamReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (outputStreamWriter != null) {
				try {
					outputStreamWriter.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (conn != null) {
				try {
					conn.disconnect();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		log.debug("get request url: {},返回值:{}", urlAddr, result.toString());
		return result.toString();
	}

	/**
	 * https get request
	 */
	public static String getSSL(String urlAddr, Map<String, Object> paramsMap, int connectTimeout, int readTimeout) throws Exception {
		log.info("get request url: {}, params: {}", urlAddr, JSONObject.toJSONString(paramsMap));
		String line;
		String params = "";
		HttpsURLConnection conn = null;
		BufferedReader bufferedReader = null;
		InputStreamReader inputStreamReader = null;
		StringBuilder result = new StringBuilder();
		TrustManager[] trustManager = {new DefaultX509TrustManager()};
		// 创建SSLContext
		SSLContext sslContext = SSLContext.getInstance("SSL");
		// 初始化
		sslContext.init(null, trustManager, new java.security.SecureRandom());
		// 获取SSLSocketFactory对象
		SSLSocketFactory ssf = sslContext.getSocketFactory();
		try {
			if (connectTimeout < 1) {
				connectTimeout = CONNECT_TIMEOUT;
			}
			if (readTimeout < 1) {
				readTimeout = READ_TIMEOUT;
			}
			if (paramsMap != null && !paramsMap.isEmpty()) {
				StringBuilder str = new StringBuilder();
				Set<String> set = paramsMap.keySet();
				for (Object o : set) {
					String key = o.toString();
					if (paramsMap.get(key) == null) {
						continue;
					}
					str.append(key).append("=").append(paramsMap.get(key)).append("&");
				}
				if (str.length() > 0) {
					params = "?" + str.substring(0, str.length() - 1);
				}
			}
			URL url = new URL(urlAddr + params);
			conn = (HttpsURLConnection) url.openConnection();
			// 设置读取超时时间
			conn.setReadTimeout(readTimeout);
			// 设置连接超时时间
			conn.setConnectTimeout(connectTimeout);
			// 设置当前实例使用的SSLSocketFactory
			conn.setSSLSocketFactory(ssf);
			conn.connect();
			inputStreamReader = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8);
			bufferedReader = new BufferedReader(inputStreamReader);
			while ((line = bufferedReader.readLine()) != null) {
				result.append(line);
			}
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (inputStreamReader != null) {
				try {
					inputStreamReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (conn != null) {
				try {
					conn.disconnect();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		log.debug("get request url: {},返回值:{}", urlAddr, result.toString());
		return result.toString();
	}

	/**
	 * https post request
	 */
	public static String postSSL(String urlAddr, Map<String, Object> paramsMap, int connectTimeout, int readTimeout) throws Exception {
		log.info("post request url: {}, params: {}", urlAddr, JSONObject.toJSONString(paramsMap));
		String line;
		String params = "";
		HttpsURLConnection conn = null;
		BufferedReader bufferedReader = null;
		InputStreamReader inputStreamReader = null;
		OutputStreamWriter outputStreamWriter = null;
		StringBuilder result = new StringBuilder();
		TrustManager[] trustManager = {new DefaultX509TrustManager()};
		// 创建SSLContext
		SSLContext sslContext = SSLContext.getInstance("SSL");
		// 初始化
		sslContext.init(null, trustManager, new java.security.SecureRandom());
		// 获取SSLSocketFactory对象
		SSLSocketFactory ssf = sslContext.getSocketFactory();
		try {
			if (connectTimeout < 1) {
				connectTimeout = CONNECT_TIMEOUT;
			}
			if (readTimeout < 1) {
				readTimeout = READ_TIMEOUT;
			}
			if (paramsMap != null && !paramsMap.isEmpty()) {
				StringBuilder str = new StringBuilder();
				Set<String> set = paramsMap.keySet();
				for (Object o : set) {
					String key = o.toString();
					if (paramsMap.get(key) == null) {
						continue;
					}
					str.append(key).append("=").append(paramsMap.get(key)).append("&");
				}
				if (str.length() > 0) {
					params = str.substring(0, str.length() - 1);
				}
			}
			URL url = new URL(urlAddr);
			conn = (HttpsURLConnection) url.openConnection();
			// 设置读取超时时间
			conn.setReadTimeout(readTimeout);
			// 设置连接超时时间
			conn.setConnectTimeout(connectTimeout);
			// 设置当前实例使用的SSLSocketFactory
			conn.setSSLSocketFactory(ssf);
			// 设置是否向HttpURLConnection输出，因为这个是post请求，参数要放在http正文内，
			// 因此需要设为true, 默认情况下是false
			conn.setDoOutput(true);
			// 不使用缓存,默认情况下是true
			conn.setUseCaches(false);
			// 设定请求的方法为"POST",默认是GET
			conn.setRequestMethod("POST");
			if (!params.isEmpty()) {
				// 此处getOutputStream会隐含的进行connect()
				outputStreamWriter = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8);
				// 写入
				outputStreamWriter.write(params);
				// 刷新该流的缓冲
				outputStreamWriter.flush();
			}
			inputStreamReader = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8);
			bufferedReader = new BufferedReader(inputStreamReader);
			while ((line = bufferedReader.readLine()) != null) {
				result.append(line);
			}
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (inputStreamReader != null) {
				try {
					inputStreamReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (outputStreamWriter != null) {
				try {
					outputStreamWriter.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (conn != null) {
				try {
					conn.disconnect();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		log.debug("get request url: {},返回值:{}", urlAddr, result.toString());
		return result.toString();
	}

	/**
	 * http post request
	 */
	public static String post(String urlAddr, String paramsStr, int connectTimeout, int readTimeout) throws Exception {
		log.info("post request url: {}, params: {}", urlAddr, paramsStr);
		String line;
		HttpURLConnection conn = null;
		BufferedReader bufferedReader = null;
		InputStreamReader inputStreamReader = null;
		OutputStreamWriter outputStreamWriter = null;
		StringBuilder result = new StringBuilder();
		try {
			if (connectTimeout < 1) {
				connectTimeout = CONNECT_TIMEOUT;
			}
			if (readTimeout < 1) {
				readTimeout = READ_TIMEOUT;
			}
			URL url = new URL(urlAddr);
			conn = (HttpURLConnection) url.openConnection();
			// 设置读取超时时间
			conn.setReadTimeout(readTimeout);
			// 设置连接超时时间
			conn.setConnectTimeout(connectTimeout);
			// 设置是否向HttpURLConnection输出，因为这个是post请求，参数要放在http正文内，
			// 因此需要设为true, 默认情况下是false
			conn.setDoOutput(true);
			// 不使用缓存,默认情况下是true
			conn.setUseCaches(false);
			// 设定请求的方法为"POST",默认是GET
			conn.setRequestMethod("POST");
			if (paramsStr != null && !paramsStr.isEmpty()) {
				// 此处getOutputStream会隐含的进行connect()
				outputStreamWriter = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8);
				// 写入
				outputStreamWriter.write(paramsStr);
				// 刷新该流的缓冲
				outputStreamWriter.flush();
			}
			inputStreamReader = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8);
			bufferedReader = new BufferedReader(inputStreamReader);
			while ((line = bufferedReader.readLine()) != null) {
				result.append(line);
			}
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (inputStreamReader != null) {
				try {
					inputStreamReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (outputStreamWriter != null) {
				try {
					outputStreamWriter.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (conn != null) {
				try {
					conn.disconnect();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		log.debug("get request url: {},返回值:{}", urlAddr, result.toString());
		return result.toString();
	}

	/**
	 * https post request
	 */
	public static String postSSL(String urlAddr, String paramsStr, int connectTimeout, int readTimeout) throws Exception {
		log.info("post request url: {}, params: {}", urlAddr, paramsStr);
		String line;
		HttpsURLConnection conn = null;
		BufferedReader bufferedReader = null;
		InputStreamReader inputStreamReader = null;
		OutputStreamWriter outputStreamWriter = null;
		StringBuilder result = new StringBuilder();
		TrustManager[] trustManager = {new DefaultX509TrustManager()};
		// 创建SSLContext
		SSLContext sslContext = SSLContext.getInstance("SSL");
		// 初始化
		sslContext.init(null, trustManager, new java.security.SecureRandom());
		// 获取SSLSocketFactory对象
		SSLSocketFactory ssf = sslContext.getSocketFactory();
		try {
			if (connectTimeout < 1) {
				connectTimeout = CONNECT_TIMEOUT;
			}
			if (readTimeout < 1) {
				readTimeout = READ_TIMEOUT;
			}
			URL url = new URL(urlAddr);
			conn = (HttpsURLConnection) url.openConnection();
			// 设置读取超时时间
			conn.setReadTimeout(readTimeout);
			// 设置连接超时时间
			conn.setConnectTimeout(connectTimeout);
			// 设置当前实例使用的SSLSocketFactory
			conn.setSSLSocketFactory(ssf);
			// 设置是否向HttpURLConnection输出，因为这个是post请求，参数要放在http正文内，
			// 因此需要设为true, 默认情况下是false
			conn.setDoOutput(true);
			// 不使用缓存,默认情况下是true
			conn.setUseCaches(false);
			// 设定请求的方法为"POST",默认是GET
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Accept", "application/json");
			conn.setRequestProperty("Content-Type", "application/json");
			conn.setRequestProperty("X-Requested-With", "XMLHttpRequest");
			conn.setRequestProperty("Origin", "https://m-search.kaola.com");
			conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36");

			if (paramsStr != null && !paramsStr.isEmpty()) {
				// 此处getOutputStream会隐含的进行connect()
				outputStreamWriter = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8);
				// 写入
				outputStreamWriter.write(paramsStr);
				// 刷新该流的缓冲
				outputStreamWriter.flush();
			}
			inputStreamReader = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8);
			bufferedReader = new BufferedReader(inputStreamReader);
			while ((line = bufferedReader.readLine()) != null) {
				result.append(line);
			}
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (inputStreamReader != null) {
				try {
					inputStreamReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (outputStreamWriter != null) {
				try {
					outputStreamWriter.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (conn != null) {
				try {
					conn.disconnect();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		log.debug("get request url: {},返回值:{}", urlAddr, result.toString());
		return result.toString();
	}

	/**
	 * ajax response
	 */
	public static void toJson(JsonElement res, HttpServletResponse response) {
		PrintWriter writer = null;
		try {
			response.setContentType("application/json;charset=utf-8");
			writer = response.getWriter();
			writer.print(new Gson().toJson(res));
		} catch (Exception e) {
			log.error("", e);
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 获取客户端ip地址
	 */
	public static String getClientIp(HttpServletRequest request) {
		// 网宿cdn的真实ip
		String ip = request.getHeader("Cdn-Src-Ip");
		if (StringUtils.isBlank(ip) || " unknown".equalsIgnoreCase(ip)) {
			// 蓝讯cdn的真实ip
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (StringUtils.isBlank(ip) || " unknown".equalsIgnoreCase(ip)) {
			// 获取代理ip
			ip = request.getHeader("X-Forwarded-For");
		}
		if (StringUtils.isBlank(ip) || " unknown".equalsIgnoreCase(ip)) {
			// 获取代理ip
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
			// 获取代理ip
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
			// 获取真实ip
			ip = request.getRemoteAddr();
		}
		return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
	}

	/**
	 * 根据IP获取地址
	 */
	public static JSONObject getIpAddress(String ip) {
		if (ip == null || ip.trim().length() < 1) {
			return null;
		}
		String code = "0";
		String url = "http://ip.taobao.com/service/getIpInfo.php?ip=" + ip;
		try {
			String res = HttpUtils.get(url, null, 0, 0);
			JSONObject json = JSONObject.parseObject(res);
			String backCode = json.getString("code");
			if (code.equals(backCode)) {
				return json.getJSONObject("data");
			}
		} catch (Exception e) {
			log.error("", e);
		}
		return null;
	}

	/**
	 * 设置下载响应
	 */
	public static void setDownLoadResponse(HttpServletRequest request, HttpServletResponse response, String fileName) throws Exception {
		String msie = "msie";
		String chrome = "chrome";
		String windows = "windows";
		String firefox = "firefox";
		String browserType = request.getHeader("User-Agent").toLowerCase();
		if (browserType.contains(firefox) || browserType.contains(chrome)) {
			fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), "ISO8859-1");
		} else if (browserType.contains(msie) || browserType.contains(windows)) {
			fileName = URLEncoder.encode(fileName, "UTF-8");
		} else {
			fileName = new String(fileName.getBytes());
		}
		// 重置
		response.reset();
		// 告知浏览器不缓存
		response.setHeader("pragma", "no-cache");
		response.setHeader("cache-control", "no-cache");
		response.setHeader("expires", "0");
		// 响应编码
		response.setCharacterEncoding("UTF-8");
		// 用给定的名称和值添加一个响应头
		response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
	}

	/**
	 * 根据流获取字符串
	 */
	public static String getInputStream(HttpServletRequest request) {
		BufferedReader bufferedReader = null;
		InputStreamReader inputStreamReader = null;
		ServletInputStream servletInputStream = null;
		StringBuilder result = new StringBuilder();
		try {
			String line;
			servletInputStream = request.getInputStream();
			inputStreamReader = new InputStreamReader(servletInputStream, StandardCharsets.UTF_8);
			bufferedReader = new BufferedReader(inputStreamReader);
			while ((line = bufferedReader.readLine()) != null) {
				result.append(line);
			}
		} catch (Exception e) {
			log.error("", e);
			e.printStackTrace();
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (inputStreamReader != null) {
				try {
					inputStreamReader.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (servletInputStream != null) {
				try {
					servletInputStream.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return result.toString();
	}


	/**
	 * 调用api测试
	 *
	 * @param urlHead      请求的url到openapi的部分，如http://gw.open.1688.com/openapi/
	 * @param urlPath      protocol/version/namespace/name/appKey
	 * @param appSecretKey 测试的app密钥，如果为空表示不需要签名
	 * @param params       api请求参数map。如果api需要用户授权访问，那么必须完成授权流程，params中必须包含access_token参数
	 * @return json格式的调用结果
	 */
	public static String callApiTest(String urlHead, String urlPath, String appSecretKey, Map<String, String> params) {
		final HttpClient httpClient = new HttpClient();
		final PostMethod method = new PostMethod(urlHead + urlPath);
		method.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");

		if (params != null) {
			for (Map.Entry<String, String> entry : params.entrySet()) {
				method.setParameter(entry.getKey(), entry.getValue());
			}
		}
		if (appSecretKey != null) {
			method.setParameter("_aop_signature", CommonUtil.signatureWithParamsAndUrlPath(urlPath, params, appSecretKey));
		}
		String response = "";
		try {
			int status = httpClient.executeMethod(method);
			if (status >= 300 || status < 200) {
				throw new RuntimeException("invoke api failed, urlPath:" + urlPath + " status:" + status + " response:" + method.getResponseBodyAsString());
			}
			response = CommonUtil.parserResponse(method);
		} catch (IOException e) {
			log.error(e.getLocalizedMessage());
		} finally {
			method.releaseConnection();
		}
		return response;
	}

	private static CloseableHttpClient httpClient;
	private static final Map<String, String> HEADERS_JSON = new HashMap<>();
	/**
	 * connectionRequestTimeout: 从连接池中获取连接的超时时间，超过该时间未拿到可用连接<br>
	 * connectTimeout: 连接上服务器(握手成功)的时间，超出该时间抛出connect timeout <br>
	 * socketTimeout: 服务器返回数据(response)的时间，超过该时间抛出read timeout<br>
	 */
	static {
		List<Header> defaultHeaders = new ArrayList<>();
		defaultHeaders.add(new BasicHeader("accept", "*/*"));
		defaultHeaders.add(new BasicHeader("connection", "Keep-Alive"));
		// 连接最多等待6秒，无响应则断开
		RequestConfig config = RequestConfig.custom().setConnectTimeout(6000).setSocketTimeout(6000).build();
		httpClient = HttpClients.custom().setDefaultRequestConfig(config).setConnectionTimeToLive(300, TimeUnit.SECONDS).setDefaultHeaders(defaultHeaders).build();
		HEADERS_JSON.put("Content-Type", "application/json;charset=utf-8");
	}


	public static String postJson(String url, String request) {
		Assert.hasText(url, "");
		String result = null;
		CloseableHttpResponse httpResponse =null;
		try {
			HttpPost httpPost = new HttpPost(url);
			String sequese = RandomStringUtils.randomAlphabetic(8);
			httpPost.addHeader("Content-Type","application/json;charset=utf-8");
			log.debug("[{}]url={}, request={}", sequese, url, request);
			StringEntity entity = new StringEntity(request, Charset.forName("utf-8"));
			httpPost.setEntity(entity);
			httpResponse = httpClient.execute(httpPost);
			if (httpResponse == null) {
				throw new MyException(RespMessage.Status.ERROR, "系统错误");
			}
			HttpEntity httpEntity = httpResponse.getEntity();
			result = EntityUtils.toString(httpEntity);
			log.debug("[{}]response={}", sequese, result);
			EntityUtils.consume(httpEntity);
		} catch (IOException e) {
			throw new MyException(RespMessage.Status.ERROR, "IO错误");
		} catch (Exception e) {
			log.error("", e);
		} finally {
			try {
				if (httpResponse != null) {
					httpResponse.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
}